package com.suredy.app.porject.ctrl;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.UUID;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.suredy.app.porject.tools.FileTool;
import com.suredy.core.helper.ApplicationContextHelper;

/**
 * 下载文件服务
 * 
 * @author VIVID.G
 * @since 2015-10-28
 * @version v0.1
 */
@WebServlet(urlPatterns = "/download/*", loadOnStartup = 0)
public class DownloadFileServlet extends HttpServlet {

	private final static Logger log = LoggerFactory.getLogger(DownloadFileServlet.class);

	private static final long serialVersionUID = 1L;

	private String CONTEXT_PATH;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);

		CONTEXT_PATH = config.getServletContext().getContextPath();
	}

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 通知客户端允许断点下载
		resp.setHeader("Accept-Ranges", "bytes");
		resp.setHeader("Content-Type", "applicatoin/octet-stream");

		// 格式：文件名/后缀/相对路径
		String params = this.params(req.getRequestURI());

		if (!this.validate(params)) {
			log.error("Invalid parameters. It is: [" + params + "]");
			return;
		}

		String fileName = this.fileName(params);
		String relativePath = this.relativePath(params);

		resp.setHeader("Content-Disposition", "attachment; filename=\"" + this.fileFullName(fileName, req.getHeader("User-Agent")) + "\"");

		FileTool ft = ApplicationContextHelper.getBeanByType(FileTool.class);

		long count = ft.output(req, resp, relativePath);

		if (count == -1) {
			resp.setCharacterEncoding("UTF-8");
			resp.setContentType("text/html; charset=utf-8");

			PrintWriter pw = resp.getWriter();

			pw.write("<script type=\"text/javascript\">");
			pw.write("alert('无法下载指定文件：" + fileName + "');");
			pw.write("</script>");

			pw.flush();
		}
	}

	private String params(String uri) throws UnsupportedEncodingException {
		String prefix = this.CONTEXT_PATH + "/download/";
		prefix = prefix.replace("/", "\\/");

		uri = URLDecoder.decode(uri, "UTF-8");

		return uri.replaceFirst(prefix, "");
	}

	private String relativePath(String params) throws UnsupportedEncodingException {
		if (!this.validate(params))
			return null;

		// 取第一段内容
		String value = params.substring(0, params.indexOf('/'));

		return URLDecoder.decode(value, "UTF-8");
	}

	private String fileName(String params) throws UnsupportedEncodingException {
		if (!this.validate(params))
			return null;

		// 取第二段内容
		String value = params.substring(params.indexOf('/') + 1);

		return URLDecoder.decode(value, "UTF-8");
	}

	private boolean validate(String params) {
		if (StringUtils.isBlank(params))
			return false;

		String[] tmp = params.split("\\/");

		if (tmp.length < 2)
			return false;

		return true;
	}

	private String fileFullName(String showName, String userAgent) {
		// new a temp fileName
		if (StringUtils.isBlank(showName))
			showName = UUID.randomUUID().toString().replace("-", "");

		try {
			if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
				// 各种IE的情况
				showName = URLEncoder.encode(showName, "UTF-8");
			} else {
				showName = new String(showName.getBytes(Charsets.UTF_8), Charsets.ISO_8859_1);
			}
		} catch (UnsupportedEncodingException e) {
		}

		return showName;
	}

}
